package com.xiashitech.agent.utils;

import com.xiashitech.agent.cache.data.CacheSync;
import com.xiashitech.agent.cache.data.Job;
import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.db.entity.DataWaterMarkConfig;
import com.xiashitech.agent.diagnosis.Spy;
import com.xiashitech.agent.diagnosis.classloader.DiagnosisClassLoader;
import com.xiashitech.agent.instrumentation.db.statement.sanitizer.impl.XSSqlSanitizer;
import com.xiashitech.agent.service.extloadproxy.AuthServiceProxy;

import java.lang.instrument.Instrumentation;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class StartupUtil {

    private static ClassLoader diagnosisClassLoader;
    public static void premainBefore(String agentArgs) {
        try {
            StartConfig.initCommonParams(agentArgs);
            StartConfig.initEnvVar();
            StartConfig.initSync(StartConfig.getParamValueFromKey(StartConfig.agentService));
            StartConfig.initSystemInfo(StartConfig.getParamValueFromKey(StartConfig.agentService));
        } catch (Throwable e) {
            StartConfig.throwableStackPrinter(e);
        }
    }
    public static void premainAfter(String agentArgs) {
        try {
            LocalMachineUtil.init();
            Job.execute();
        } catch (Throwable e) {
            StartConfig.throwableStackPrinter(e);
        }
    }
    public static void onLineDiagnosis(Instrumentation inst, String agentService, String systemId, String microServiceId) {
        try {
            // 获取各种Hook
            Class<?> adviceWeaverClass = diagnosisClassLoader.loadClass("com.xiashitech.agent.diagnosis.advisor.AdviceWeaver");
            // 初始化全局间谍
            Spy.initForAgentLauncher(
                    adviceWeaverClass.getMethod("methodOnBegin",
                            int.class,
                            ClassLoader.class,
                            String.class,
                            String.class,
                            String.class,
                            Object.class,
                            Object[].class),
                    adviceWeaverClass.getMethod("methodOnReturnEnd",
                            Object.class,
                            int.class),
                    adviceWeaverClass.getMethod("methodOnThrowingEnd",
                            Throwable.class,
                            int.class),
                    adviceWeaverClass.getMethod("methodOnInvokeBeforeTracing",
                            int.class,
                            Integer.class,
                            String.class,
                            String.class,
                            String.class),
                    adviceWeaverClass.getMethod("methodOnInvokeAfterTracing",
                            int.class,
                            Integer.class,
                            String.class,
                            String.class,
                            String.class),
                    adviceWeaverClass.getMethod("methodOnInvokeThrowTracing",
                            int.class,
                            Integer.class,
                            String.class,
                            String.class,
                            String.class,
                            String.class)
            );
            Class<?> classOfGaServer = diagnosisClassLoader.loadClass("com.xiashitech.agent.diagnosis.server.GaServer");
            classOfGaServer.getMethod("init",Instrumentation.class,String.class,String.class,String.class).invoke(null,inst,agentService,systemId,microServiceId);
        } catch (Throwable e) {
        }
    }

    public static ClassLoader setDiagnosisClassLoader(String agentPath) {
        if (diagnosisClassLoader == null) {
            synchronized(StartupUtil.class) {
                if (diagnosisClassLoader == null) {
                    try {
                        diagnosisClassLoader = new DiagnosisClassLoader(agentPath);
                    } catch (Throwable e) {
                        StartConfig.throwableStackPrinter(e);
                    }
                }
            }
        }
        return diagnosisClassLoader;
    }

    public static ClassLoader getDiagnosisClassLoader() {
        return diagnosisClassLoader;
    }

    public static void initLocalDBAndRegPushChanel(){
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> {
            // AuthService.getInstance().init();
            AuthServiceProxy.initAuthService();
        });
        executor.shutdown();
    }
}
